package net.xumf.service.master.impl;

import com.google.common.collect.Lists;
import net.xumf.dao.master.DictRepository;
import net.xumf.domain.master.Dict;
import net.xumf.service.master.DictService;
import net.xumf.support.common.BaseServiceImpl;
import net.xumf.support.consts.Constants;
import net.xumf.support.converter.PageConverter;
import net.xumf.support.model.bo.KeyValueBO;
import net.xumf.support.model.dto.PageDTO;
import net.xumf.support.model.vo.PageVO;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class DictServiceImpl extends BaseServiceImpl<DictRepository, Dict, Integer> implements DictService {


    @Override
    public PageVO getByPage(PageDTO pageDTO) {
        Pageable pageable = PageConverter.pageVOToPageable(pageDTO);
        Page<Dict> rolePage = repository.findAllByParentId(Constants.Normal.ROOT_ID, pageable);
        return PageConverter.pageToPageDTO(rolePage);
    }

    @Override
    @Transactional
    public <S extends Dict> Dict add(S pojo) {
        // 更新父字典hasChild为true
        Integer parentId = pojo.getParentId();
        if (Constants.Normal.ROOT_ID != parentId) {
            getById(parentId).ifPresent(o -> {
                o.setHasChild(true);
                update(o);
            });
        }
        pojo.setKey(UUID.randomUUID().toString().replace("-", ""));
        return super.add(pojo);
    }

    @Override
    @Transactional
    public void remove(Integer pojoId) {
        Optional<Dict> optionalDict = getById(pojoId);
        optionalDict.ifPresent(o -> {
            super.remove(pojoId);
            if (Constants.Normal.ROOT_ID == o.getParentId()) {
                repository.deleteByParentId(o.getDictId());
            } else {
                long count = repository.countByParentId(o.getParentId());
                if (count == 0 || count == 1) {
                    getById(o.getParentId()).ifPresent(p -> {
                        p.setHasChild(false);
                        update(p);
                    });
                }
            }
        });
    }

    @Override
    public List<Dict> getByParentId(Integer parentId) {
        return Lists.newArrayList(repository.findAllByParentIdOrderBySequenceAsc(parentId));
    }

    @Override
    public long getLongByKey(String key) {
        return repository.findByKey(key).map(o -> Long.parseLong(o.getValue())).orElseThrow(ClassCastException::new);
    }

    @Override
    public int getIntByKey(String key) {
        return repository.findByKey(key).map(o -> Integer.parseInt(o.getValue())).orElseThrow(ClassCastException::new);
    }

    @Override
    public String getStringByKey(String key) {
        return repository.findByKey(key).map(Dict::getValue).orElseThrow(ClassCastException::new);
    }

    @Override
    public double getDoubleByKey(String key) {
        return repository.findByKey(key).map(o -> Double.parseDouble(o.getValue())).orElseThrow(ClassCastException::new);
    }

    @Override
    public float getFloatByKey(String key) {
        return repository.findByKey(key).map(o -> Float.parseFloat(o.getValue())).orElseThrow(ClassCastException::new);
    }

    @Override
    public List<KeyValueBO> getAllSubDictByKey(String key) {
        return repository.findAllByParentKey(key).stream()
                .map(o -> new KeyValueBO(o.getValue(), o.getName())).collect(Collectors.toList());
    }

    @Override
    public Optional<KeyValueBO> getOneSubDictByKey(String key) {
        return repository.findAllByParentKey(key).stream()
                .map(o -> new KeyValueBO(o.getValue(), o.getName())).findFirst();
    }
}
